<script setup>
import { onMounted, onUnmounted, watch } from 'vue';
import { useRouter } from 'vue-router'
import store from '@/store'

import axios from 'axios'
import amisRequest from '../utils/amisRequest'
import { getToken } from '@/utils/utils';

function loadScript(src, callback) {
  const script = document.createElement("script");
  script.setAttribute("type", "text/javascript");
  script.setAttribute("src", src);
  script.onload = () => callback();
  script.onerror = () => callback(new Error(`Failed to load ${src}`));
  document.body.appendChild(script);
}

function loadStyles(styles) {
  for (const path of styles) {
    const style = document.createElement("link");
    style.setAttribute("rel", "stylesheet");
    style.setAttribute("type", "text/css");
    style.setAttribute("href", path);
    document.head.appendChild(style);
  }
}
function loadSDK() {
  return (new Promise((resolve, reject) => {
    if (window.amisRequire) {
      resolve();
      return;
    }
    loadStyles([
      "/amis/sdk/sdk.css",
      "/amis/sdk/helper.css",
      "/amis/sdk/iconfont.css",
      "/amis/sdk/antd.css",
    ]);
    loadScript("/amis/sdk/sdk.js", (err) => {
      if (err) {
        reject(err);
        return;
      }
      resolve();
    });
  }));
}

const props = defineProps({
  /** The amis JSON schema */
  schema: {
    type: Object,
    required: true,
  },
  /** 赋予 amis 顶层数据域的值 */
  locals: {
    type: Object,
    default: () => ({}),
  },
  /** 控制 amis 的属性，一般都用不上 */
  props: {
    type: Object,
    default: () => ({}),
  },
  /** 环境变量，用于控制 amis 的行为，需要使用 amis 用户实现部分接口 */
  env: {
    type: Object,
    default: () => ({}),
  },
});

const updateProps = function() {
  this.amisInstance?.updateProps({
    data: {
      ...this.locals,
    },
    context: this.context,
    ...this.props,
  });
}

watch(
  () => props.locals,
  (newLocals, oldLocals) => {
    console.log(`count changed from ${oldLocals} to ${newLocals}`);
    this.updateProps();
  },
  { deep: true }
);

watch(
  () => props.props,
  (newProps, oldProps) => {
    console.log(`count changed from ${newProps} to ${oldProps}`);
    this.updateProps();
  },
  { deep: true }
);

watch(
  () => store.state.user.info,
  (newProps, oldProps) => {
    console.log(`count changed from ${newProps} to ${oldProps}`);
    this.updateProps();
  },
  { deep: true }
);

/** The amis component is ready */
const emit = defineEmits(['ready']);

let amisInstance = null;
const router = useRouter();

onMounted(async () => {
  await loadSDK();
  const scoped = window.amisRequire('amis/embed');
  const { normalizeLink } = amisRequire("amis-core");
  
  const instance = scoped.embed(
    '#amis-component',
    props.schema,
    {
      // 3.1.0 开始可以传入 context 数据，无论哪层都可以使用到这个里面的数据。适合用来传递一些平台数据。
      context: {
        API_HOST: import.meta.env.VITE_BASE_API,
        TOKEN: getToken(),
        ...props.env,
      },
      // 可以通过 props 里的 locals 属性来赋予 amis 顶层数据域的值
      data: {
        ...props.locals,
        USER: store.state.user.info,
        PERMISSIONS: store.state.user.permissions,
      },
      // 	其它的初始 props，一般不用传。
      ...props.props,
      // locale: 'en-US' // props 中可以设置语言，默认是中文
    },
    {
      // 环境变量，可以理解为这个渲染器工具的配置项。
      jumpTo: (to, action) => {
        if (to === 'goBack') {
          return router.back();
        }
        to = normalizeLink(to);
        if (action && action.actionType === 'url') {
          action.blank === false ? router.push(to) : window.open(to);
          return;
        }
        // 主要是支持 nav 中的跳转
        if (action && to && action.target) {
          window.open(to, action.target);
          return;
        }
        if (/^https?:\/\//.test(to)) {
          router.replace(to);
        } else {
          router.push(to);
        }
      },
      updateLocation: (to, replace) => {
        if (to === 'goBack') {
          return router.back();
        }
        to = normalizeLink(to);
        replace ? router.replace(to) : router.push(to);
      },
      fetcher: (url, method, data, responseType, config, headers) => {
        config = config || {};
        config.withCredentials = true;
        responseType && (config.responseType = responseType);

        if (config.cancelExecutor) {
          config.cancelToken = new axios.CancelToken(
            config.cancelExecutor
          );
        }

        config.headers = headers || {};

        if (method !== 'post' && method !== 'put' && method !== 'patch') {
          if (data) {
            config.params = data;
          }

          return amisRequest(url, method, data, responseType,config, headers);
        } else if (data && data instanceof FormData) {
          config.headers = config.headers || {};
          config.headers['Content-Type'] = 'multipart/form-data';
        } else if (
          data &&
          typeof data !== 'string' &&
          !(data instanceof Blob) &&
          !(data instanceof ArrayBuffer)
        ) {
          data = JSON.stringify(data);
          config.headers = config.headers || {};
          config.headers['Content-Type'] = 'application/json';
        }

        return amisRequest(url, method, data, responseType,config, headers);
      },
      isCancel: (value) => axios.isCancel(value),
      theme: 'antd',
      ...props.env,
    },
    () => {
      emit('ready', { instance });
    },
  );
  amisInstance = instance;
  window.amisInstance = instance;
});

onUnmounted(() => {
  amisInstance?.unmount();
});

</script>

<template>
  <div id="amis-component"></div>
</template>